package services

import (
	"errors"
	"io/ioutil"
	"path/filepath"
	"strings"
	"vala/tools"
)

type ServiceManager struct {
	services map[string]*ServiceDefine
}

func NewServiceManager() *ServiceManager {
	var extensionsDir = filepath.Join(tools.GetBasePath(), "Extensions")
	files, error := ioutil.ReadDir(extensionsDir)
	if error != nil {
		panic(error)
	}
	// 获取已有service
	var serviceDefines = make(map[string]*ServiceDefine)
	for _, file := range files {
		if file.IsDir() {
			serviceDefines[strings.ToLower(file.Name())] = NewServiceDefine(file.Name(), filepath.Join(extensionsDir, file.Name()))
		}
	}

	return &ServiceManager{
		services: serviceDefines,
	}
}

// 获取服务
func (sm *ServiceManager) GetService(serviceFlag string) (Service, error) {
	// 缓存服务对象
	if serviceDefine, ok := sm.services[serviceFlag]; ok {
		// 由服务定义构建出实例
		return serviceDefine.Instance(), nil
	}

	return nil, errors.New("service not exists")
}

func (sm *ServiceManager) GetAll() map[string]*ServiceDefine {
	return sm.services
}

// 服务定义
type ServiceDefine struct {
	Name     string
	Dir      string
	instance Service
}

func NewServiceDefine(name string, dir string) *ServiceDefine {
	return &ServiceDefine{
		Name: name,
		Dir:  dir,
	}
}

func (sd *ServiceDefine) Instance() Service {
	if sd.instance == nil {
		switch strings.ToLower(sd.Name) {
		case "php":
			sd.instance = NewPHPService(filepath.Join(sd.Dir, "7.3", "php-cgi.exe"))
		case "nginx":
			sd.instance = NewNginxService(filepath.Join(sd.Dir, "nginx.exe"))
		//case "mysql5.7":
		//	sd.instance = NewMysqlService(sd.Dir, filepath.Join(sd.Dir, "bin", "mysqld.exe"))
		default:
			sd.instance = NewCustomService(sd.Dir)
		}
	}

	return sd.instance
}
